home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-05-01 | 13.4 KB | 297 lines | [TEXT/MPS ] |
- {
- File: DebuggerSupport.p
-
- Contains: Public interface to kernel services for debuggers
-
- Version: Technology: System 8
- Release: Universal Interfaces 3.0d3 on Copland DR1
-
- Copyright: © 1984-1996 by Apple Computer, Inc. All rights reserved.
-
- Bugs?: If you find a problem with this file, send the file and version
- information (from above) and the problem description to:
-
- Internet: apple.bugs@applelink.apple.com
- AppleLink: APPLE.BUGS
-
- }
- {$IFC UNDEFINED UsingIncludes}
- {$SETC UsingIncludes := 0}
- {$ENDC}
-
- {$IFC NOT UsingIncludes}
- UNIT DebuggerSupport;
- INTERFACE
- {$ENDC}
-
- {$IFC UNDEFINED __DEBUGGERSUPPORT__}
- {$SETC __DEBUGGERSUPPORT__ := 1}
-
- {$I+}
- {$SETC DebuggerSupportIncludes := UsingIncludes}
- {$SETC UsingIncludes := 1}
-
- {$IFC UNDEFINED __TYPES__}
- {$I Types.p}
- {$ENDC}
- {$IFC UNDEFINED __KERNEL__}
- {$I Kernel.p}
- {$ENDC}
- {$IFC UNDEFINED __MACHINEEXCEPTIONS__}
- {$I MachineExceptions.p}
- {$ENDC}
-
- {$PUSH}
- {$ALIGN POWER}
- {$LibExport+}
-
- {$IFC FOR_SYSTEM8_PREEMPTIVE }
- {
- In addition to the normal kernel API, the kernel provides a set of services
- which are specific to debuggers. These services are all accessed through the
- DebuggerSupport library.
- This first service is debugger registration and unregistration. For a debugger
- to register itself with the kernel, it calls DSRegisterDebugger. (The kernel
- allows only one registered debugger; multiple debuggers can be supported
- externally by registering a dispatching entity as the debugger.) When a debugger
- has successfully registered itself, it is able to receive exceptions from
- debuggable tasks. Unregistering is simply the reverse of registering. The
- kernel automatically unregisters a debugger when it terminates if the debugger
- has not already unregistered itself. DSRegisterDebugger should be the first
- call made to this library.
- To receive an exception, the debugger calls DSWaitForException, passing it a
- pointer to a DSExceptionRecord and a time limit. This call blocks until either
- an exception arrives or the time limit expires (pass kDurationForever to wait
- indefinitely). Note that this semantic essentially requires the debugger to
- be multithreaded.
- A DSExceptionRecord contains the ID of the excepted task, along with the IDs
- of the task's team and address space, and a message ID corresponding to the
- particular exception. The details of the exception are contained in the
- exception record's ExceptionInformation structure, which includes pointers
- to the task's registers and other exception state. The debugger may directly
- modify this exception data, and, within limits, these changes will be forced
- into the task's state upon resuming execution. (Changes to certain parts of
- the exception data, such as the privileged and interrupt enable bits of the
- exception MSR, will be ignored.)
- DSResumeFromException is used to resume the excepted task's execution or to
- propagate the exception on. It takes as parameters the exception ID and an
- exception return status. The status may be either noErr or any nonzero error
- code. noErr signifies that the debugger has cured the exception and the excepted
- task should continue execution, using the state from the exception data. Any
- other status value will cause the exception to be propagated to the installed
- exception handler, if any. If there is no installed handler, or if that handler
- fails to cure the exception, the exception is again presented to the debugger in
- another message. This time, returning a nonzero return status will cause the
- task to be terminated. (Double notification of exceptions allows a debugger to
- catch exceptions either first, last, or at both times.)
- Not all exceptions will be sent to the debugger. Exceptions in kernel tasks
- or in kernel code which runs on behalf of user tasks is not debuggable through
- normal means. Furthermore, exceptions occurring in privileged tasks with
- hardware interrupts disabled, or during execution at secondary interrupt level,
- or while running message system Accept functions, fall into the same category
- as kernel exceptions and are not sent to the debugger.
- The debugger may call DSHoldTasks to request the kernel to hold a task or set
- of tasks, making them ineligible for execution. The tasks are specified with a
- task ID and scope (task only, task and children, task family, or task team). If
- any task to be held is already blocked inside the kernel, e.g. due to a page
- fault, I/O operation, or message send, holding it will cause it to remain
- ineligible even after it has unblocked. Releasing held tasks with DSReleaseTasks
- allows them to become eligible again.
- DSGetTaskState is used to determine a task's scheduler state (runnable or blocked),
- and, if blocked, what its PC and SP values were at the point it blocked. If a
- task is running a software interrupt it will have scheduler state for both its
- normal execution and the execution of the software interrupt.
- DSReadMemory and DSWriteMemory are used to access task memory. To read memory,
- the debugger simply calls DSReadMemory. To modify memory, the debugger must first
- call DSCreateMemoryAccess to obtain a memory write access right to the desired page
- of memory. Using that access right, it may then call DSWriteMemory to perform the
- modification. DSWriteMemory performs appropriate processor cache synchronization and
- backing storage coordination to support modifying code memory, e.g. for instruction
- breakpoints. DSDeleteMemoryAccess is used to release an access right.
- Some implementations of the kernel and hardware may support data breakpoints. To
- find out what data breakpoint support (if any) is available, the debugger calls
- DSGetDataBreakpointInformation. DSSetDataBreakpoint is used to set or clear a
- data breakpoint. The implementation may cause excess exceptions which will have to
- be filtered out by the debugger: breakpoints may occur in the wrong address space
- or on an address which is outside the range specified but which lies within the
- resolution range supported by the implementation.
- Exception notification record
- }
-
- TYPE
- DSExceptionRecordPtr = ^DSExceptionRecord;
- DSExceptionRecord = RECORD
- exceptedTaskID: TaskID;
- exceptedKernelProcessID: KernelProcessID;
- exceptedTaskAddrSpaceID: AddressSpaceID;
- exceptionID: MessageID;
- exception: ExceptionInformation;
- END;
-
- { Task state record }
- DSKernelStatePtr = ^DSKernelState;
- DSKernelState = RECORD
- kernelState: SchedulerState;
- PC: LogicalAddress;
- SP: LogicalAddress;
- END;
-
- DSTaskStatePtr = ^DSTaskState;
- DSTaskState = RECORD
- taskState: DSKernelState;
- swiState: DSKernelState;
- END;
-
- { ID to specify write access rights to a particular page in logical memory }
- DSMemoryAccessID = ^LONGINT;
- { SchedulerState values }
-
- CONST
- kInactiveState = ' ';
- kPageFaultState = 'PFLT';
- kMessageSendState = 'MSND';
- kMessageReceiveState = 'MRCV';
- kHeldState = 'HELD';
- kEventFlagState = 'EFLG';
- kTerminatingOtherProcessState = 'OTRM';
- kTerminatingCurrentProcessState = 'CTRM';
- kTimerDelayState = 'DLYQ';
- kKernelQueueState = 'QBLK';
- kRunState = 'RUN ';
- kSemaphoreReadState = 'MSRD';
- kSemaphoreWriteState = 'MSWR';
- kTaskStartingState = 'STRT';
- kTaskTerminatingState = 'TERM';
-
- {
- Describes the data breakpoint facility provided by the current implementation.
- maxBreakpoints is the maximum number of data breakpoints available (may be zero).
- breakpointResolution determines the worst case range of addresses to which a data
- breakpoint applies, as follows: if the nominal breakpoint address is addr, the
- actual range of addresses breakpointed may, in the worst case, be
- [(addr & ~(breakpointResolution - 1)) ..
- (addr & ~(breakpointResolution - 1)) + breakpointResolution - 1].
- }
-
- TYPE
- DSDataBreakpointInformationPtr = ^DSDataBreakpointInformation;
- DSDataBreakpointInformation = RECORD
- maxBreakpoints: ItemCount;
- breakpointResolution: ByteCount;
- END;
-
-
- CONST
- kDataBreakpointInformationVersion = 1;
-
- {
- The access types to which a data breakpoint should apply. Use
- kDSBreakDisable to clear a data breakpoint. Note that the implementation
- may not support breakpointing read and write accesses independently; in
- that case specifying either option will have the same effect (break on
- any access).
- }
-
- TYPE
- DSDataBreakpointOptions = OptionBits;
-
- CONST
- kDSBreakDisable = $00000000;
- kDSBreakOnReadAccess = $00000001;
- kDSBreakOnWriteAccess = $00000002;
-
- {
- Debugger Services functions
- Register the debugger. Returns kernelIDErr if there is already a debugger
- registered.
- }
- FUNCTION DSRegisterDebugger: OSStatus; C;
- {
- Unregister the debugger. This is also done automatically by the kernel if
- the debugger terminates.
- }
- FUNCTION DSUnregisterDebugger: OSStatus; C;
- { Wait specified amount of time for an exception message from the kernel. }
- FUNCTION DSWaitForException(VAR exceptionRecord: DSExceptionRecord; timeLimit: Duration): OSStatus; C;
- {
- Resume execution of a task halted by an earlier exception. If exceptionReturnStatus
- is noErr, resume the task, else propagate the exception. If the propagated exception
- remains unhandled, a second exception notification will be generated.
- }
- FUNCTION DSResumeFromException(exceptionID: MessageID; exceptionReturnStatus: OSStatus): OSStatus; C;
- { Make the specified task(s) ineligible for execution, until released by DSReleaseTasks. }
- FUNCTION DSHoldTasks(taskID: TaskID; scope: TaskRelationship): OSStatus; C;
- { Make the specified held task(s) eligible again for execution. }
- FUNCTION DSReleaseTasks(taskID: TaskID; scope: TaskRelationship): OSStatus; C;
- {
- Get the scheduler state for a task. The task may be in a software interrupt or in
- normal execution; if normal, state->swiState.kernelState will be kInactiveState. In
- either case, the appropriate state->taskState.kernelState or state->swiState.kernelState
- will be kRunState if the task is running, and if so the corresponding PC and SP values
- are invalid and will be returned as zero. If the task is blocked in normal execution
- then state->taskState.PC and state->taskState.SP will reflect the PC and SP at the time
- of the system call which caused the task to block. Similarly, if the task is blocked
- in a software interrupt, hence not running, then state->swiState.PC and state->swiState.SP
- will be nonzero.
- }
- FUNCTION DSGetTaskState(taskID: TaskID; VAR state: DSTaskState): OSStatus; C;
- {
- Create a write access right to the page for logical address dstAddr in address
- space addrSpaceID. This makes the page physically resident and prevents subsequent
- reads or writes of the page from or to backing storage. The access right is returned
- in memAccessID.
- }
- FUNCTION DSCreateMemoryAccess(addrSpaceID: AddressSpaceID; dstAddr: LogicalAddress; VAR memAccessID: DSMemoryAccessID): OSStatus; C;
- {
- Modify the memory to which an access right has been obtained. memAccessID is the access
- right, dstAddr is the target address, srcDataPtr points to the source data to be written,
- and numBytes is the size of the write. The range [dstAddr..dstAddr + numBytes - 1] must lie
- entirely within the page specified by the access right. If the destination memory is code,
- processor caches will be synchronized appropriately.
- }
- FUNCTION DSWriteMemory(memAccessID: DSMemoryAccessID; dstAddr: LogicalAddress; srcDataPtr: UNIV Ptr; numBytes: ByteCount): OSStatus; C;
- {
- Delete an access right and allow normal backing storage activity for that page. memAccessID
- is the access right. Note: changes to the page up to this point will NOT be written to
- backing storage.
- }
- FUNCTION DSDeleteMemoryAccess(memAccessID: DSMemoryAccessID): OSStatus; C;
- {
- Read memory. srcAddr is the address to read from, addrSpaceID specifies the address space,
- dstDataPtr points to the debugger buffer into which to copy the data, and numBytes is the
- size of the read.
- }
- FUNCTION DSReadMemory(addrSpaceID: AddressSpaceID; srcAddr: LogicalAddress; dstDataPtr: UNIV Ptr; numBytes: ByteCount): OSStatus; C;
- {
- Set a data breakpoint. addrSpaceID specifies the address space, which may or may not be
- used. breakAddr is the logical address to break on. numBytes is a hint as to the range
- of addresses to break on. The address range [breakAddr .. (breakAddr + numBytes -1)] must
- lie within the worst case data breakpoint resolution which the implmentation supports, as
- determined via DSGetDataBreakpointInformation. A data breakpoint hit will result in a
- memory access exception of type kDataBreakpointException. The implementation may cause
- excess exceptions which will have to be filtered out by the debugger, e.g. breakpoints
- may occur in the wrong address space or on an address which is outside the range specified
- but which lies within the resolution range supported by the implementation. To "fix up"
- a memory reference which triggered a data breakpoint exception without removing the
- data breakpoint, use DSReadMemory or DSWriteMemory. Data breakpoints may be disallowed
- on certain addresses which are used by system code; DSSetDataBreakpoint will return
- kernelInUseErr for such addresses.
- }
- FUNCTION DSSetDataBreakpoint(addrSpaceID: AddressSpaceID; breakAddr: LogicalAddress; numBytes: ByteCount; options: DSDataBreakpointOptions): OSStatus; C;
- {
- Get information about data breakpoint support. Returns the number of breakpoints available in
- the current implementation and the worst case address resolution of a data breakpoint.
- }
- FUNCTION DSGetDataBreakpointInformation(version: PBVersion; VAR info: DSDataBreakpointInformation): OSStatus; C;
- {$ENDC}
- {$ALIGN RESET}
- {$POP}
-
- {$SETC UsingIncludes := DebuggerSupportIncludes}
-
- {$ENDC} {__DEBUGGERSUPPORT__}
-
- {$IFC NOT UsingIncludes}
- END.
- {$ENDC}
-